package net.apps.core.meta;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

import net.apps.core.ApplFactory;
import net.apps.core.Protocol;

public class ProtocolMetaImpl implements Meta {
	
	private final int id;
	private final Class<? extends Protocol> clazz;
	private final String name;
	private final String description;
	private final Collection<Meta> decls; 
	private final Meta[] typedecls;
	
	public ProtocolMetaImpl(Class<? extends Protocol> clazz) {
		AProtocol ann = clazz.getAnnotation(AProtocol.class);
		this.id = ApplFactory.allocateProtocolId(ann.name());
		this.clazz = clazz;
		this.name = ann.name();
		this.description = ann.description();
		this.typedecls = new Meta[128];

		ArrayList<Meta> decls = new ArrayList<Meta>();
		
		for (Class<?> msgclz : clazz.getDeclaredClasses()) {
			if (msgclz.isAnnotationPresent(AMessage.class)) {
				DeclMetaImpl dm = new DeclMetaImpl(this, msgclz);
				typedecls[dm.getId()] = dm;
				decls.add(dm);
			}
		}
		this.decls = Collections.unmodifiableList(decls);
	}
	
	@Override
	public Decl getDeclKind() {
		return Decl.PROTOCOL;
	}

	@Override
	public int getId() {
		return id;
	}

	@Override
	public Meta getType() {
		return MetaFactory.metaOfProtocol;
	}

	@Override
	public Collection<Meta> getConstraints() {
		return Collections.emptyList();
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public String getDescription() {
		return description;
	}

	@Override
	public Meta getParent() {
		return null;
	}
	
	@Override
	public Collection<Meta> getDecls() {
		return decls;
	}

	@Override
	public Meta getTypeDecl(int id) {
		return typedecls[id];
	}

	@Override
	public Object getValue() {
		return clazz;
	}

}
